﻿using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Net;
using LitJson;
using System.Threading;
class ServerManager
{
    private static ServerManager _instance;
    public static ServerManager Instance()
    {
        if (_instance == null)
        {
            _instance = new ServerManager();
        }
        return _instance;
    }

    Dictionary<string, SocketClient> dic = new Dictionary<string, SocketClient>();
    List<UserData> list = new List<UserData>();

    public static object lockObj = new object();
    TcpListener listener;
    string IP = "192.168.11.25";
    int Port = 8500;
    private int HeartInterval = 5 * 1000;


    int PlayerCount = 2;
    int DeadCount = 0;

    private ServerManager()
    {
        IPAddress address = IPAddress.Parse(IP);
        listener = new TcpListener(address, Port);

        listener.Start();
        Console.WriteLine("服务器启动，开始侦听");

        listener.BeginAcceptTcpClient(OnAccecpt,null);

        Timer timer = new Timer(CallBack,null,HeartInterval, HeartInterval);
    }

    private void CallBack(object state)
    {
        List<string> keys = new List<string>();
        foreach (var item in dic.Keys)
        {
            keys.Add(item);
        }
        for (int i = 0; i < keys.Count; i++)
        {
            SocketClient client = dic[keys[i]];
            client.SendMessage(Protocol.HeartBeat);
            client.timeOut++;
            if (client.timeOut > 5)
            {
                Console.WriteLine(client.userdata.username + "心跳超时，断开连接");
                RemoveClient(client);
            }
        }
    }

    //接收客户端连接
    void OnAccecpt(IAsyncResult result)
    {
        TcpClient client = listener.EndAcceptTcpClient(result);
        SocketClient remote = new SocketClient(client);

       
        lock(listener)
        {
            listener.BeginAcceptTcpClient(OnAccecpt, null);
        }
    }


    //广播所有人消息<包含自己>
    public void BroadAll(int protocal, string msg)
    {
        lock (lockObj)
        {
            for (int i = 0; i < list.Count; i++)
            {
                string key = list[i].username;
                dic[key].SendMessage(protocal, msg);
            }
        }
    }
    public void BroadAll(int protocal)
    {
        lock (lockObj)
        {
            for (int i = 0; i < list.Count; i++)
            {
                string key = list[i].username;
                dic[key].SendMessage(protocal);
            }
        }
    }

    //广播给其他人
    public void BroadOther(SocketClient client,int protocal, string msg)
    {
        lock (lockObj)
        {
            for (int i = 0; i < list.Count; i++)
            {
                string key = list[i].username;
                if (key != client.userdata.username)
                {
                    dic[key].SendMessage(protocal, msg);
                }
            }
        }
    }

    //把断开的客户端，移除掉
    public void RemoveClient(SocketClient client)
    {
        lock (lockObj)
        {
            //连接socket但未登陆的用户不用移除
            if (client.userdata != null)
            {
                string username = client.userdata.username;

                Console.WriteLine(username + "：断开链接");
                dic.Remove(client.userdata.username);
                list.Remove(client.userdata);

                //广播给所有人，玩家退出游戏
                BroadAll(Protocol.PlayerLogOut_CMD, JsonMapper.ToJson(client.userdata));
            }
        }

    }

    
    public void OnMessage(SocketClient client,int protocol,string msg)
    {
        switch (protocol)
        {
            case Protocol.Login_CMD:
                //玩家超过限定人数，防止继续进入
                if (list.Count >= PlayerCount)
                {
                    return;
                }
                bool hasPlayer = false;
                UserData user = JsonMapper.ToObject<UserData>(msg);
                //已经存在玩家
                if (dic.ContainsKey(user.username))
                {
                    //还没有往字典存，client就是当前登录的玩家
                    client.SendMessage(Protocol.PlayerRepeatExit_CMD);
                }
                else//把新连接用户存储起来
                {
                    //登录后，才保存用户的信息
                    client.userdata = JsonMapper.ToObject<UserData>(msg);
                    dic.Add(client.userdata.username, client);
                    list.Add(client.userdata);//存储到list中
                    //赋值index
                    client.userdata.index = list.IndexOf(client.userdata);

                    //广播新用户登录
                    string userJson = JsonMapper.ToJson(client.userdata);
                    BroadOther(client, protocol, userJson);

                    //通知新用户登录成功
                    dic[client.userdata.username].SendMessage(Protocol.SelfLogin_CMD, userJson);
                    //通知新用户，其他玩家数据
                    dic[client.userdata.username].SendMessage(Protocol.OtherPlayerInfo_CMD, JsonMapper.ToJson(list));
                }
                break;
            case Protocol.PlayerPosition_CMD:
                BroadOther(client, protocol, msg);
                break;
            case Protocol.PlayerMove_CMD:
                BroadOther(client, protocol, msg);
                break;
            case Protocol.PlayerFire_CMD:
                BroadOther(client, protocol, msg);
                break;
            case Protocol.PlayerOnHit_CMD:
                HitData data = JsonMapper.ToObject<HitData>(msg);
                string username = data.targetUsername;

                foreach (var item in dic)
                {
                    if (item.Value.userdata.username == username)
                    {
                        data.hp = --item.Value.userdata.hp;
                        BroadAll(protocol, JsonMapper.ToJson(data));
                        //玩家已经死亡
                        if (data.hp <= 0)
                        {
                            DeadCount++;
                            BroadAll(Protocol.PlayerDead_CMD, JsonMapper.ToJson(item.Value.userdata));

                            //剩余最后一名玩家
                            if (DeadCount >= PlayerCount - 1)
                            {
                                for (int i = 0; i < list.Count; i++)
                                {
                                    if (list[i].hp > 0)
                                    {
                                        BroadAll(Protocol.PlayerWin_CMD, JsonMapper.ToJson(list[i]));
                                        break;
                                    }
                                }
                            }
                        }
                        break;
                    }
                }
                break;
            case Protocol.HeartBeat:
                client.timeOut = 0;
                break;
            case Protocol.PlayerReady_CMD://找到该玩家，广播他的所有信息
                client.userdata.isReady = true;
                string json = JsonMapper.ToJson(client.userdata);
                BroadAll(protocol, json);

                //全部准备，开始游戏
                int readyCount = 0;
                foreach (var item in list)
                {
                    if (item.isReady)
                    {
                        readyCount++;
                    }
                }
                if (readyCount >= PlayerCount)
                {
                    DeadCount = 0;
                    BroadAll(Protocol.ReadyGoToGame_CMD, JsonMapper.ToJson(list));
                }
                break;
            default:
                break;
        }
    }
}
